package com.naiterui.ehp.bs.emr.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.naiterui.common.repository.page.PageParamVO;
import com.naiterui.common.repository.page.PageVO;
import com.naiterui.ehp.bp.bo.doctor.RecomDoctorBO;
import com.naiterui.ehp.bp.bo.doctor.RecomPatientBO.AgeUnitEunm;
import com.naiterui.ehp.bp.bo.doctor.RecomUserInfoBO;
import com.naiterui.ehp.bp.bo.patient.FamilyBO;
import com.naiterui.ehp.bp.bo.patient.FamilyBO.GenderEnum;
import com.naiterui.ehp.bp.bo.patient.PersonalDoctorBO;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.beans.BeanUtil;
import com.naiterui.ehp.bp.utils.lang.ConfigUtil;
import com.naiterui.ehp.bs.emr.dto.DoctorInfoDTO;
import com.naiterui.ehp.bs.emr.dto.MedicalRecordDetailDTO;
import com.naiterui.ehp.bs.emr.entity.mongo.MDrink;
import com.naiterui.ehp.bs.emr.entity.mongo.MFamilyDisease;
import com.naiterui.ehp.bs.emr.entity.mongo.MSelectOrOthers;
import com.naiterui.ehp.bs.emr.entity.mongo.MSmoke;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecord;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordDoctor;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordFromPatient;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordPatient;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordRecom;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordScale;
import com.naiterui.ehp.bs.emr.entity.mongo.MedicalRecordScreen;
import com.naiterui.ehp.bs.emr.entity.mongo.PatientMedicalRecord;
import com.naiterui.ehp.bs.emr.entity.mongo.SignInfo;
import com.naiterui.ehp.bs.emr.exception.ExceptionCodes;
import com.naiterui.ehp.bs.emr.remote.IEmrRemoter;
import com.naiterui.ehp.bs.emr.repository.mongo.MedicalRecordRepository;
import com.naiterui.ehp.bs.emr.repository.mongo.PatientDiseaseRepository;
import com.naiterui.ehp.bs.emr.repository.mongo.PatientMedicalRecordRepository;
import com.naiterui.ehp.bs.emr.service.IMedicalRecordService;
import com.naiterui.ehp.bs.emr.service.IPatientCaseService;
import com.naiterui.ehp.bs.emr.utils.Constants;
import com.naiterui.ehp.bs.emr.utils.ImageUrlUtil;
import com.naiterui.ehp.bs.emr.utils.LimitValueConfig;
import com.naiterui.ehp.bs.emr.utils.enums.ERelation;
import com.naiterui.ehp.bs.emr.vo.ImgFileVO;
import com.naiterui.ehp.bs.emr.vo.LimitConfigVO;
import com.naiterui.ehp.bs.emr.vo.MCaseFileImgVO;
import com.naiterui.ehp.bs.emr.vo.patient.CaseFileResultVO;
import com.naiterui.ehp.bs.emr.vo.patient.CaseFileVO;
import com.naiterui.ehp.bs.emr.vo.patient.DoctorMedicalRecordVO;
import com.naiterui.ehp.bs.emr.vo.patient.DocumentInitVO;
import com.naiterui.ehp.bs.emr.vo.patient.DocumentResultVO;
import com.naiterui.ehp.bs.emr.vo.patient.DocumentVO;
import com.naiterui.ehp.bs.emr.vo.patient.FamilyVO;
import com.naiterui.ehp.bs.emr.vo.patient.MDrinkVO;
import com.naiterui.ehp.bs.emr.vo.patient.MFamilyDiseaseVO;
import com.naiterui.ehp.bs.emr.vo.patient.MSelectOrOthersVO;
import com.naiterui.ehp.bs.emr.vo.patient.MSmokeVO;
import com.naiterui.ehp.bs.emr.vo.patient.MenstrualVO;
import com.naiterui.ehp.bs.emr.vo.patient.PatientCaseDetailVO;
import com.naiterui.ehp.bs.emr.vo.patient.SignInfoVO;
import com.naiterui.ehp.bs.emr.vo.scale.DoctorScaleVO;
import com.naiterui.ehp.bs.emr.vo.scale.PatientScaleVO;

import cn.hutool.core.collection.CollectionUtil;

/**
 * 病例业务逻辑实现层
 *
 * @since 2.18
 */

@Service
public class PatientCaseServiceImpl extends AbstractMedicalRecordServiceImpl implements IPatientCaseService {
    private static final Logger LOGGER = LoggerFactory.getLogger(PatientCaseServiceImpl.class);

    @Autowired
    private IEmrRemoter remoter;
    @Autowired
    private MedicalRecordRepository medicalRecordRepository;
    @Autowired
    private PatientMedicalRecordRepository patientMedicalRecordRepository;
    @Autowired
    private PatientDiseaseRepository patientDiseaseRepository;

    @Autowired
    private IMedicalRecordService medicalRecordService;

    @Value("${ehp.domain.img}")
    private String imgDomain;

    private static final String EHP_HOSPITAL_NAME = ConfigUtil.getString("ehp.hospital.name");


    @Override
    public DocumentInitVO initDocument(Long patientId, Long familyId) throws BusinessException {
        PatientMedicalRecord patientMedicalRecord = patientMedicalRecordRepository.findByPatientIdAndFamilyIdAndStatus(patientId, familyId,
                Constants.CASE_STATUS_DRAFT);
        DocumentInitVO documentInitVO = new DocumentInitVO();
        DocumentVO documentVO = convertCaseToDocumentInitVO(patientMedicalRecord);
        String amcSeqNum;
        if (documentVO != null && StringUtils.isNotEmpty(documentVO.getAmcSeqNum())) {
            amcSeqNum = documentVO.getAmcSeqNum();
        } else {
            amcSeqNum = patientId + "" + System.currentTimeMillis();
        }
        documentInitVO.setAmcSeqNum(amcSeqNum);

        // 获取家庭成员信息判断是否孕期
        FamilyBO familyBo = remoter.getFamilyByID(familyId);
        if (familyBo == null || familyBo.getId() == null) {
            LOGGER.warn("错误的成员id，familyId: {}", familyId);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        boolean showPregnancy = checkPregnancy(familyBo);
        FamilyVO familyVo = new FamilyVO();
        BeanUtils.copyProperties(familyBo, familyVo);
        documentInitVO.setShowPregnancy(showPregnancy);
        documentInitVO.setDocumentVO(documentVO);
        documentInitVO.setFamilyVO(familyVo);
        return documentInitVO;
    }

    /**
     * 校验是否是孕期
     * PatientCaseServiceImpl.checkPregnancy()
     *
     * @param family
     *
     * @return
     *
     * @Date 2018年5月30日
     * @since 2.18
     */
    private boolean checkPregnancy(FamilyBO family) {
        // 20-45岁含，女性，默认显示孕期和哺乳期
        if (GenderEnum.val(family.getGender()) == GenderEnum.GENDER_FEMALE) {
            Integer age = family.getAge();
            String ageUnit = family.getAgeUnit();
            LimitConfigVO limitVO = LimitValueConfig.getLimitConfig(LimitValueConfig.LIMIT_PREGNANCY_AGE);
            return AgeUnitEunm.val(ageUnit) == AgeUnitEunm.YEAR && age >= limitVO.getMin() && age <= limitVO.getMax();
        }
        return false;
    }

    /**
     * 转换病例mongo实例为基本病情VO
     * PatientCaseServiceImpl.convertCaseToDocumentInitVO()
     *
     * @param patientMedicalRecord
     *
     * @return
     *
     * @Date 2018年5月30日
     * @since 2.18
     */
    private DocumentVO convertCaseToDocumentInitVO(PatientMedicalRecord patientMedicalRecord) {
        if (patientMedicalRecord == null) {
            return null;
        }
        DocumentVO documentVO = new DocumentVO();
        BeanUtils.copyProperties(patientMedicalRecord, documentVO);
        MedicalRecordPatient medicalRecordPatient = patientMedicalRecord.getMedicalRecordPatient();
        if (medicalRecordPatient.getMedicAllergys() != null) {
            MSelectOrOthersVO medicAllergys = new MSelectOrOthersVO();
            BeanUtils.copyProperties(medicalRecordPatient.getMedicAllergys(), medicAllergys);
            documentVO.setMedicAllergys(medicAllergys);
        }
        if (medicalRecordPatient.getPastDiseases() != null) {
            MSelectOrOthersVO pastDiseases = new MSelectOrOthersVO();
            BeanUtils.copyProperties(medicalRecordPatient.getPastDiseases(), pastDiseases);
            documentVO.setPastDiseases(pastDiseases);
        }
        if (medicalRecordPatient.getHereditaryDiseases() != null) {
            MSelectOrOthersVO hereditaryDiseases = new MSelectOrOthersVO();
            BeanUtils.copyProperties(medicalRecordPatient.getHereditaryDiseases(), hereditaryDiseases);
            documentVO.setHereditaryDiseases(hereditaryDiseases);
        }

        if (medicalRecordPatient.getSmoke() != null) {
            MSmokeVO smoke = new MSmokeVO();
            BeanUtils.copyProperties(medicalRecordPatient.getSmoke(), smoke);
            documentVO.setSmoke(smoke);
        }

        if (medicalRecordPatient.getDrink() != null) {
            MDrinkVO drink = new MDrinkVO();
            BeanUtils.copyProperties(medicalRecordPatient.getDrink(), drink);
            MSelectOrOthers wines = medicalRecordPatient.getDrink().getWines();
            if (wines != null) {
                MSelectOrOthersVO winesVO = new MSelectOrOthersVO();
                BeanUtils.copyProperties(wines, winesVO);
                drink.setWines(winesVO);
            }
            documentVO.setDrink(drink);
        }
        documentVO.setCaseId(patientMedicalRecord.getId());
        return documentVO;
    }

    @Override
    public DocumentResultVO saveDocument(Long patientId, Long familyId, DocumentVO documentVO) throws BusinessException {
        // 校验参数
        documentVO.validation();
        // 获取家庭成员信息判断是否孕期
        FamilyBO family = remoter.getFamilyByID(familyId);
        if (family == null) {
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        boolean showPregnancy = checkPregnancy(family);
        // 孕期则孕期项必填
        if (showPregnancy) {
            if (documentVO.getPregnancy() == null) {
                LOGGER.warn("孕期哺乳期未输入，patientId：{}, familyId: {}", patientId, familyId);
                throw new BusinessException(ExceptionCodes.PREGNANCY_EMPTY); // 孕期哺乳期未输入提示文案
            }
        }

        // 新增或修改草稿
        PatientMedicalRecord patientMedicalRecord = patientMedicalRecordRepository.findByPatientIdAndFamilyIdAndStatus(patientId, familyId,
                Constants.CASE_STATUS_DRAFT);
        if (patientMedicalRecord == null) {// 新增草稿
            patientMedicalRecord = convertDocument2Case(documentVO, family, patientId, null);
            patientMedicalRecordRepository.save(patientMedicalRecord);
        } else {// 更新草稿
            convertDocument2Case(documentVO, family, patientId, patientMedicalRecord);
            patientMedicalRecordRepository.update(patientMedicalRecord);
        }

        DocumentResultVO resultVO = new DocumentResultVO();
        // 获取关注医生信息
        Long doctorId = documentVO.getDoctorId();
        if (doctorId != null) {
            resultVO.setDoctorCount(1);
            resultVO.setDoctorId(doctorId);
        } else {
            List<PersonalDoctorBO> doctorList = remoter.getPersonalDoctorList(patientId);
            int count = doctorList.size();
            resultVO.setDoctorCount(count);
            if (count == 1) {
                resultVO.setDoctorId(doctorList.get(0).getDoctorId());
            }
        }

        resultVO.setCaseId(patientMedicalRecord.getId());
        return resultVO;
    }

    /**
     * 将基本病情VO转化为病例mongo实例
     * PatientCaseServiceImpl.convertDocument2Case()
     *
     * @param paramVO
     * @param family
     * @param patientId
     *
     * @return
     *
     * @Date 2018年5月31日
     * @since 2.18
     */
    private PatientMedicalRecord convertDocument2Case(DocumentVO paramVO, FamilyBO family, Long patientId,
                                                      PatientMedicalRecord patientMedicalRecord) {
        boolean amcModifyFlag = false;
        Date date = new Date();
        if (patientMedicalRecord == null) {
            amcModifyFlag = true;
            patientMedicalRecord = new PatientMedicalRecord();
            BeanUtils.copyProperties(family, patientMedicalRecord, "id");
            patientMedicalRecord.setPatientId(patientId);
            patientMedicalRecord.setFamilyId(family.getId());
            patientMedicalRecord.setMedicalRecordPatient(new MedicalRecordPatient());
            patientMedicalRecord.setCreateAt(date);
            patientMedicalRecord.setCreateBy("patient:" + patientId);
        } else {
            patientMedicalRecord.setChangeAt(date);
            patientMedicalRecord.setChangeBy("patient:" + patientId);
        }
        BeanUtils.copyProperties(paramVO, patientMedicalRecord);
        MedicalRecordPatient medicalRecordPatient = patientMedicalRecord.getMedicalRecordPatient();
        //复制身高，体重、病情描述
        BeanUtils.copyProperties(paramVO, medicalRecordPatient);
        List<MFamilyDisease> mFamilyDiseases = Optional.ofNullable(paramVO.getFamilyDiseases()).orElse(Lists.newArrayList())
                                                       .stream()
                                                       .map(mfdvo -> {
                                                           MFamilyDisease mFamilyDisease = new MFamilyDisease();
                                                           mFamilyDisease.setMember(mfdvo.getMember());
                                                           MSelectOrOthers mSelectOrOthers = new MSelectOrOthers();
                                                           BeanUtils.copyProperties(Optional.ofNullable(mfdvo.getDisease())
                                                                                            .orElse(new MSelectOrOthersVO()), mSelectOrOthers);
                                                           mFamilyDisease.setDisease(mSelectOrOthers);
                                                           return mFamilyDisease;
                                                       }).collect(Collectors.toList());
        medicalRecordPatient.setFamilyDiseases(mFamilyDiseases);

        BeanUtils.copyProperties(paramVO, medicalRecordPatient);
        if (paramVO.getMedicAllergys() != null) {
            MSelectOrOthers medicAllergys = new MSelectOrOthers();
            BeanUtils.copyProperties(paramVO.getMedicAllergys(), medicAllergys);
            medicalRecordPatient.setMedicAllergys(medicAllergys);
        }
        if (paramVO.getPastDiseases() != null) {
            MSelectOrOthers pastDiseases = new MSelectOrOthers();
            BeanUtils.copyProperties(paramVO.getPastDiseases(), pastDiseases);
            medicalRecordPatient.setPastDiseases(pastDiseases);
        }
        if (paramVO.getHereditaryDiseases() != null) {
            MSelectOrOthers hereditaryDiseases = new MSelectOrOthers();
            BeanUtils.copyProperties(paramVO.getHereditaryDiseases(), hereditaryDiseases);
            medicalRecordPatient.setHereditaryDiseases(hereditaryDiseases);
        }

        if (paramVO.getSmoke() != null) {
            MSmoke smoke = new MSmoke();
            BeanUtils.copyProperties(paramVO.getSmoke(), smoke);
            medicalRecordPatient.setSmoke(smoke);
        }

        if (paramVO.getDrink() != null) {
            MDrink drink = new MDrink();
            BeanUtils.copyProperties(paramVO.getDrink(), drink);
            MSelectOrOthersVO winesVO = paramVO.getDrink().getWines();
            if (winesVO != null) {
                MSelectOrOthers wines = new MSelectOrOthers();
                BeanUtils.copyProperties(winesVO, wines);
                drink.setWines(wines);
            }
            medicalRecordPatient.setDrink(drink);
        }
        if (paramVO.getDoctorId() != null) {
            patientMedicalRecord.setSource(Constants.CASE_SOURCE_ASK);
        } else {
            patientMedicalRecord.setSource(Constants.CASE_SOURCE_SELF);
        }
        patientMedicalRecord.setStatus(Constants.CASE_STATUS_DRAFT);
        return patientMedicalRecord;
    }

    @Override
    public CaseFileResultVO saveCaseFile(Long patientId, Long familyId, CaseFileVO caseFileVO) throws BusinessException {
        caseFileVO.validCaseParam();
        String caseId = caseFileVO.getCaseId();
        PatientMedicalRecord patientMedicalRecord = patientMedicalRecordRepository.findByIdAndPatientId(caseId, patientId);
        Assert.notNull(patientMedicalRecord, String.format("患者病历为null id：%s", caseId));
        convertCaseFileVO2Case(caseFileVO, patientMedicalRecord);

        // 校验绑定医生,如果有绑定医生，直接向IM发送通知
        Long doctorId = patientMedicalRecord.getDoctorId();
        boolean sendflag = false;
        boolean needpay = false;
        if (doctorId != null) {
            sendflag = true;
        } else {
            List<PersonalDoctorBO> doctorList = remoter.getPersonalDoctorList(patientId);
            int count = doctorList.size();
            if (count == 1) {
                sendflag = true;
                doctorId = doctorList.get(0).getDoctorId();
                patientMedicalRecord.setDoctorId(doctorId);
            }
        }

        patientMedicalRecordRepository.update(patientMedicalRecord);
        if (sendflag) {
            Integer imRet = remoter.sendImCase(patientId, doctorId, caseId);
            if (imRet == Constants.IM_RET_NEEDPAY) {
                needpay = true;
            }
        }
        return new CaseFileResultVO(needpay, doctorId);
    }

    /**
     * 将病例VO 转为实体对象
     * PatientCaseServiceImpl.convertCaseFileVO2Case()
     *
     * @param paramVO
     * @param patientMedicalRecord
     *
     * @Date 2018年6月1日
     * @since 2.18
     */
    private void convertCaseFileVO2Case(CaseFileVO paramVO, PatientMedicalRecord patientMedicalRecord) {
        if (paramVO == null || patientMedicalRecord == null) {
            return;
        }
        //复制病历基础信息
        BeanUtils.copyProperties(paramVO, patientMedicalRecord, "id");
        //复制患者自己填写的病历信息
        MedicalRecordPatient medicalRecordPatient = patientMedicalRecord.getMedicalRecordPatient();
        BeanUtils.copyProperties(paramVO, medicalRecordPatient);
        patientMedicalRecord.setStatus(Constants.CASE_STATUS_FINISH);
        patientMedicalRecord.setChangeAt(new Date());
        patientMedicalRecord.setFinishTime(System.currentTimeMillis());
    }

    @Override
    public Integer sendCase(Long patientId, Long doctorId, String caseId) throws BusinessException {
        PatientMedicalRecord patientMedicalRecord = patientMedicalRecordRepository.findByIdAndPatientId(caseId, patientId);
        Assert.notNull(patientMedicalRecord, String.format("患者病历为null id：%s", caseId));
        patientMedicalRecord.setDoctorId(doctorId);
        patientMedicalRecordRepository.update(patientMedicalRecord);
        return remoter.sendImCase(patientId, doctorId, caseId);
    }

    @Override
    public String syncCaseToDoctor(Long patientId, String caseId) {
        PatientMedicalRecord patientMedicalRecord = patientMedicalRecordRepository.findByIdAndPatientId(caseId, patientId);
        Assert.notNull(patientMedicalRecord, String.format("患者病历为null id：%s", caseId));
        MedicalRecord medicalRecord = convertCaseToMedicalRecord(patientMedicalRecord);
        medicalRecordRepository.save(medicalRecord);
        // 同步病例成员信息，已经存在的不用再同步
        Long doctorId = patientMedicalRecord.getDoctorId();
        Integer relation = patientMedicalRecord.getRelation();
        boolean hasContainFamily = medicalRecordScreenRepository.existsByDoctorIdAndPatientIdAndRelation(doctorId, patientId, relation);
        if (!hasContainFamily) {
            MedicalRecordScreen recordScreen = new MedicalRecordScreen();
            recordScreen.setDoctorId(doctorId);
            recordScreen.setPatientId(patientId);
            recordScreen.setRelation(relation);
            ERelation eRelation = ERelation.val(relation);
            if (eRelation != null) {
                recordScreen.setRelationName(eRelation.getName());
            }
            recordScreen.setCreateAt(new Date());
            recordScreen.setCreateBy("patient:" + patientId);
            medicalRecordScreenRepository.save(recordScreen);
        }
        return medicalRecord.getId();
    }

    /**
     * 转换患者病例为医生病例
     * PatientCaseServiceImpl.convertCaseToMedicalRecord()
     *
     * @param patientMedicalRecord
     *
     * @return
     *
     * @Date 2018年6月1日
     * @since 2.18
     */
    private MedicalRecord convertCaseToMedicalRecord(PatientMedicalRecord patientMedicalRecord) {
        MedicalRecord medicalRecord = new MedicalRecord();
        BeanUtils.copyProperties(patientMedicalRecord, medicalRecord, "id");
        medicalRecord.setHospitalName(patientMedicalRecord.getHospitalName());
        medicalRecord.setDepartment(patientMedicalRecord.getDepartmentName());
        medicalRecord.setCaseType(MedicalRecord.CASETYPE_PATIENTRECORD);
        medicalRecord.setCreateAt(new Date());
        medicalRecord.setCreateBy("patient:" + patientMedicalRecord.getPatientId());

        MedicalRecordFromPatient medicalRecordFromPatient = new MedicalRecordFromPatient();
        MedicalRecordPatient medicalRecordPatient = patientMedicalRecord.getMedicalRecordPatient();
        BeanUtils.copyProperties(medicalRecordPatient, medicalRecordFromPatient);
        medicalRecordFromPatient.setPatientCaseId(patientMedicalRecord.getId());
        medicalRecordFromPatient.setPatientCreateDate(patientMedicalRecord.getCreateAt());
        medicalRecordFromPatient.setFinishTime(patientMedicalRecord.getFinishTime());
        medicalRecord.setRecordPatient(medicalRecordFromPatient);
        return medicalRecord;
    }

    /**
     * 组装医生发送病例信息
     * param patientMedicalRecord
     *
     * @return
     */
    private DoctorMedicalRecordVO assembleCaseInfo(PatientMedicalRecord patientMedicalRecord) {
        DoctorMedicalRecordVO doctorMedicalRecordVO = new DoctorMedicalRecordVO();
        //病历作废状态
        doctorMedicalRecordVO.setMedicalRecordiInvalid(Optional.ofNullable(patientMedicalRecord.getInvalid())
                                                               .orElse(MedicalRecord.INVALID_STATUS_NORMAL));
        //病历作废时间
        doctorMedicalRecordVO.setMedicalRecordiInvalidTime(patientMedicalRecord.getInvalidTime());
        MedicalRecordDoctor medicalRecordDoctor = patientMedicalRecord.getDoctorMedicalRecord();

        BeanUtils.copyProperties(medicalRecordDoctor, doctorMedicalRecordVO);

        MedicalRecordRecom medicalRecordRecom = medicalRecordDoctor.getRecom();
        if (medicalRecordRecom != null) {
            doctorMedicalRecordVO.setRecommendId(medicalRecordRecom.getRecommendId());
            //推荐作废状态
            doctorMedicalRecordVO.setPrescriptionInvalid(medicalRecordRecom.getInvalid());
        }

        // 组装图片地址
        List<ImgFileVO> imgListVo = Optional.ofNullable(medicalRecordDoctor.getImgList())
                                            .orElse(Lists.newArrayList())
                                            .stream()
                                            .map(imgFile -> {
                                                String url = ImageUrlUtil.getMedicalRecordImg(imgFile.getUrl());
                                                return new ImgFileVO(imgFile.getUuid(), url);
                                            }).collect(Collectors.toList());
        doctorMedicalRecordVO.setImgList(imgListVo);
        List<String> diagnosisList = medicalRecordDoctor.getDiagnosisList();
        // 组装诊断信息
        doctorMedicalRecordVO.setDiagnosis(Joiner.on("，").join(Optional.ofNullable(diagnosisList).orElse(Lists.newArrayList())));

        //量表
        MedicalRecordScale medicalRecordDoctorScale = medicalRecordDoctor.getScale();
        if (Objects.nonNull(medicalRecordDoctorScale)) {
            doctorMedicalRecordVO.setDoctorScaleVO(new DoctorScaleVO(medicalRecordDoctorScale.getExtBizId()));
        }
        doctorMedicalRecordVO.setTemplateName(medicalRecordDoctor.getTemplateName());
        return doctorMedicalRecordVO;
    }

    private PatientCaseDetailVO convertCaseToDetailVO(PatientMedicalRecord patientMedicalRecord) {
        PatientCaseDetailVO detailVO = new PatientCaseDetailVO();
        BeanUtils.copyProperties(patientMedicalRecord, detailVO);
        Integer source = patientMedicalRecord.getSource();
        switch (source) {
            case Constants.CASE_SOURCE_ASK:
                //医生邀请填写
                handlePatientWrite(detailVO, patientMedicalRecord.getMedicalRecordPatient());
                break;
            case Constants.CASE_SOURCE_SELF:
                //自己添加
                handlePatientWrite(detailVO, patientMedicalRecord.getMedicalRecordPatient());
                break;
            case Constants.CASE_SOURCE_DOCTOR:
                // 医生推送
                detailVO.setDoctorMedicalRecord(assembleCaseInfo(patientMedicalRecord));
                break;
            case Constants.CASE_SOURCE_SCALE:
                //患者填写量表
                String extBizId = patientMedicalRecord.getRecordScale().getExtBizId();
                detailVO.setPatientScale(new PatientScaleVO(extBizId));
                break;
            default:
                LOGGER.warn("当前病历来源不需要处理 recordId:{} source:{}", patientMedicalRecord.getId(), source);
        }

        if (patientMedicalRecord.getAge() != null) {
            String age = patientMedicalRecord.getAge() + Optional.ofNullable(patientMedicalRecord.getAgeUnit()).orElse("");
            detailVO.setAge(age);
        }
        detailVO.setMember(patientMedicalRecord.getRelation());

        return detailVO;
    }

    /**
     * 构建医生邀请填写和患者主动填写病历
     *
     * @param detailVO
     * @param medicalRecordPatient
     */
    private void handlePatientWrite(PatientCaseDetailVO detailVO, MedicalRecordPatient medicalRecordPatient) {
        //就诊时间
        detailVO.setVistingTime(medicalRecordPatient.getVistingTime());
        //TODO 2018/11/21 4:07 PM wangzehao 这里需要使用beanutil
        if (medicalRecordPatient.getMedicAllergys() != null) {
            MSelectOrOthersVO medicAllergys = new MSelectOrOthersVO();
            BeanUtils.copyProperties(medicalRecordPatient.getMedicAllergys(), medicAllergys);
            if (!medicAllergys.isEmpty()) {
                detailVO.setMedicAllergys(medicAllergys);
            }
        }
        if (medicalRecordPatient.getPastDiseases() != null) {
            MSelectOrOthersVO pastDiseases = new MSelectOrOthersVO();
            BeanUtils.copyProperties(medicalRecordPatient.getPastDiseases(), pastDiseases);
            if (!pastDiseases.isEmpty()) {
                detailVO.setPastDiseases(pastDiseases);
            }
        }

        if (medicalRecordPatient.getHereditaryDiseases() != null) {
            MSelectOrOthersVO hereditaryDiseases = new MSelectOrOthersVO();
            BeanUtils.copyProperties(medicalRecordPatient.getHereditaryDiseases(), hereditaryDiseases);
            if (!hereditaryDiseases.isEmpty()) {
                detailVO.setHereditaryDiseases(hereditaryDiseases);
            }
        }

        if (medicalRecordPatient.getSmoke() != null) {
            MSmokeVO smoke = new MSmokeVO();
            BeanUtils.copyProperties(medicalRecordPatient.getSmoke(), smoke);
            if (!smoke.isEmpty()) {
                detailVO.setSmoke(smoke);
            }
        }
        BeanUtils.copyProperties(medicalRecordPatient, detailVO);
        // 处理家族病史，过滤历史数据中的空对象
        List<MFamilyDiseaseVO> familyDiseaseVOList = Optional.ofNullable(medicalRecordPatient.getFamilyDiseases())
                                                             .orElse(Lists.newArrayList())
                                                             .stream()
                                                             .map(disease -> {
                                                                 MFamilyDiseaseVO mFamilyDiseaseVO = new MFamilyDiseaseVO();
                                                                 BeanUtils.copyProperties(disease, mFamilyDiseaseVO);
                                                                 MSelectOrOthers diseaseBean = disease.getDisease();
                                                                 if (diseaseBean != null) {
                                                                     MSelectOrOthersVO diseaseVO = new MSelectOrOthersVO();
                                                                     BeanUtils.copyProperties(diseaseBean, diseaseVO);
                                                                     mFamilyDiseaseVO.setDisease(diseaseVO);
                                                                 }
                                                                 return mFamilyDiseaseVO;
                                                             }).filter(MFamilyDiseaseVO::isNotEmpty).collect(Collectors.toList());

        detailVO.setFamilyDiseases(familyDiseaseVOList);


        if (medicalRecordPatient.getDrink() != null) {
            MDrinkVO drink = new MDrinkVO();
            BeanUtils.copyProperties(medicalRecordPatient.getDrink(), drink);
            MSelectOrOthers wines = medicalRecordPatient.getDrink().getWines();
            if (wines != null) {
                MSelectOrOthersVO winesVO = new MSelectOrOthersVO();
                BeanUtils.copyProperties(wines, winesVO);
                if (!winesVO.isEmpty()) {
                    drink.setWines(winesVO);
                }
            }
            if (!drink.isEmpty()) {
                detailVO.setDrink(drink);
            }
        }
        List<MCaseFileImgVO> adviceList = new ArrayList<>();
        if (medicalRecordPatient.getAdviceList() != null) {
            BeanUtil.copyList(medicalRecordPatient.getAdviceList(), adviceList, MCaseFileImgVO.class);
            fillImgDomain(adviceList);
            detailVO.setAdviceList(adviceList);
        }
        if (medicalRecordPatient.getPrescriptionList() != null) {
            List<MCaseFileImgVO> prescriptionList = new ArrayList<>();
            BeanUtil.copyList(medicalRecordPatient.getPrescriptionList(), prescriptionList, MCaseFileImgVO.class);
            fillImgDomain(prescriptionList);
            detailVO.setPrescriptionList(prescriptionList);
        }
        if (medicalRecordPatient.getCheckList() != null) {
            List<MCaseFileImgVO> checkList = new ArrayList<>();
            BeanUtil.copyList(medicalRecordPatient.getCheckList(), checkList, MCaseFileImgVO.class);
            fillImgDomain(checkList);
            detailVO.setCheckList(checkList);
        }
    }

    /**
     * 病例图片加域名
     * PatientCaseServiceImpl.fillImgDomain()
     *
     * @param imgList
     *
     * @Date 2018年6月5日
     * @since 2.18
     */
    private void fillImgDomain(List<MCaseFileImgVO> imgList) {
        Optional.ofNullable(imgList)
                .orElse(Lists.newArrayList())
                .stream()
                .filter(caseFileImgVO -> StringUtils.isNotEmpty(caseFileImgVO.getImgUrl()))
                .forEachOrdered(caseFileImgVO -> caseFileImgVO.setImgUrl(ImageUrlUtil.getCaseImgDomain(caseFileImgVO.getImgUrl())));
    }

    //原病例详情
    //    public PatientCaseDetailVO getCaseDetail2(Long patientId, String caseId) {
    //        PatientMedicalRecord patientMedicalRecord = patientMedicalRecordRepository.findByIdAndPatientId(caseId, patientId);
    //        Assert.notNull(patientMedicalRecord, String.format("患者病历为null id：%s", caseId));
    //        return convertCaseToDetailVO(patientMedicalRecord);
    //    }

    //原病例列表
    //    public PageVO<PatientCaseDetailVO> getCasePageList2(Long patientId, PageParamVO pageParamVO) throws BusinessException {
    //        Pageable pageable = pageParamVO.getPageable(Sort.by(Sort.Order.desc("finishTime")));
    //        Page<PatientMedicalRecord> patientMedicalRecords = patientMedicalRecordRepository.getCasePageByPatientId(patientId, pageable);
    //        List<PatientMedicalRecord> patientMedicalRecordList = patientMedicalRecords.getContent();
    //        //量表ID集合
    //        Set<String> extBizIds = patientMedicalRecordList.stream()
    //                                                        .filter(patientMedicalRecord -> patientMedicalRecord.getSource() == Constants
    // .CASE_SOURCE_SCALE)
    //                                                        .map(PatientMedicalRecord::getRecordScale)
    //                                                        .map(MedicalRecordScale::getExtBizId)
    //                                                        .collect(Collectors.toSet());
    //        List<PatientCaseDetailVO> caseVOList = patientMedicalRecordList.stream()
    //                                                                       .map(this::convertCaseToDetailVO)
    //                                                                       .filter(Objects::nonNull)
    //                                                                       .peek(patientCaseDetailVO -> patientCaseDetailVO.setAmcId(""))
    //                                                                       .peek(patientCaseDetailVO -> patientCaseDetailVO.setAmcResult(null))
    //                                                                       //将病例图片放入一个集合中
    //                                                                       .peek(this::processImgList)
    //                                                                       //设置患者填写的金数据表单
    //                                                                       .peek(p -> {
    //                                                                           PatientScaleVO patientScale = p.getPatientScale();
    //                                                                           if (patientScale != null) {
    //                                                                               String extBizId = patientScale.getExtBizId();
    //                                                                               LOGGER.warn("没有查询到量表信息,只设置量表编号 extBizId：{}", extBizId);
    //                                                                               p.setPatientScale(new PatientScaleVO(extBizId));
    //                                                                           }
    //                                                                       })
    //                                                                       .collect(Collectors.toList());
    //        return PageVO.newBuilder()
    //                     .pageNo(pageParamVO.getNum())
    //                     .pageSize(pageParamVO.getPage())
    //                     .totalCount((int) patientMedicalRecords.getTotalElements())
    //                     .result(caseVOList)
    //                     .build();
    //    }


    @Override
    public PageVO<PatientCaseDetailVO> getCasePageListByDoctor(Long patientId, Long doctorId, PageParamVO pageParamVO) throws BusinessException {
        Pageable pageable = pageParamVO.getPageable(Sort.by(Sort.Order.desc("finishTime")));
        Page<PatientMedicalRecord> patientMedicalRecords = patientMedicalRecordRepository.getCasePageByPatientAndDoctorId(patientId, doctorId,
                pageable);
        List<PatientMedicalRecord> patientMedicalRecordList = patientMedicalRecords.getContent();
        //量表ID集合
        Set<String> extBizIds = patientMedicalRecordList.stream()
                                                        .filter(patientMedicalRecord -> patientMedicalRecord.getSource() == Constants.CASE_SOURCE_SCALE)
                                                        .map(PatientMedicalRecord::getRecordScale)
                                                        .map(MedicalRecordScale::getExtBizId)
                                                        .collect(Collectors.toSet());
        List<PatientCaseDetailVO> caseVOList = patientMedicalRecordList.stream()
                                                                       .map(this::convertCaseToDetailVO)
                                                                       .filter(Objects::nonNull)
                                                                       .peek(patientCaseDetailVO -> patientCaseDetailVO.setAmcId(""))
                                                                       .peek(patientCaseDetailVO -> patientCaseDetailVO.setAmcResult(null))
                                                                       //将病例图片放入一个集合中
                                                                       .peek(this::processImgList)
                                                                       //设置患者填写的金数据表单
                                                                       .peek(p -> {
                                                                           PatientScaleVO patientScale = p.getPatientScale();
                                                                           if (patientScale != null) {
                                                                               String extBizId = patientScale.getExtBizId();
                                                                               LOGGER.warn("没有查询到量表信息,只设置量表编号 extBizId：{}", extBizId);
                                                                               p.setPatientScale(new PatientScaleVO(extBizId));
                                                                           }
                                                                       })
                                                                       .collect(Collectors.toList());
        return PageVO.newBuilder()
                     .pageNo(pageParamVO.getNum())
                     .pageSize(pageParamVO.getPage())
                     .totalCount((int) patientMedicalRecords.getTotalElements())
                     .result(caseVOList)
                     .build();
    }

    /**
     * 将病例图片放入一个集合中
     * PatientCaseServiceImpl.processImgList()
     *
     * @param detailVO
     *
     * @Date 2018年6月8日
     * @since 2.18
     */
    private void processImgList(PatientCaseDetailVO detailVO) {
        // 设置图片集合
        List<MCaseFileImgVO> adviceList = detailVO.getAdviceList();
        List<MCaseFileImgVO> prescriptionList = detailVO.getPrescriptionList();
        List<MCaseFileImgVO> checkList = detailVO.getCheckList();
        List<MCaseFileImgVO> imgList = new ArrayList<>(Optional.ofNullable(adviceList).orElse(Lists.newArrayList()));
        imgList.addAll(Optional.ofNullable(prescriptionList).orElse(Lists.newArrayList()));
        imgList.addAll(Optional.ofNullable(checkList).orElse(Lists.newArrayList()));
        detailVO.setImgList(imgList);
    }

    //==================版本分割线=======================

    @Override
    public PageVO<PatientCaseDetailVO> getCasePageList(Long patientId, Long inquirerId, PageParamVO pageParamVO) throws BusinessException {
        PageVO<MedicalRecordDetailDTO> page = medicalRecordService.findByPatientId(patientId, inquirerId, pageParamVO);
        List<MedicalRecordDetailDTO> recordList = page.getResult();

        List<PatientCaseDetailVO> caseVOList = recordList.stream()
                                                         .filter(Objects::nonNull)
                                                         .map(s -> covertToCaseDetail(s))
                                                         .collect(Collectors.toList());
        return PageVO.newBuilder()
                     .pageNo(pageParamVO.getNum())
                     .pageSize(pageParamVO.getPage())
                     .totalCount(page.getTotalCount())
                     .result(caseVOList)
                     .build();
    }

    @Override
    public PageVO<PatientCaseDetailVO> getCaseByPatient(Long patientId, PageParamVO pageVO) throws BusinessException {
        PageVO<MedicalRecordDetailDTO> page = medicalRecordService.findPatientCaseByPatient(patientId, pageVO.getPageable());
        List<MedicalRecordDetailDTO> recordList = page.getResult();

        List<PatientCaseDetailVO> caseVOList = recordList.stream()
                                                         .filter(Objects::nonNull)
                                                         .map(s -> covertToCaseDetail(s))
                                                         .collect(Collectors.toList());
        return PageVO.newBuilder()
                     .pageNo(pageVO.getNum())
                     .pageSize(pageVO.getPage())
                     .totalCount(page.getTotalCount())
                     .result(caseVOList)
                     .build();
    }

    @Override
    public PatientCaseDetailVO getCaseDetail(Long patientId, String caseId) throws BusinessException {
        MedicalRecordDetailDTO recordDetail = medicalRecordService.findById(caseId);

        Assert.notNull(recordDetail, String.format("患者病历为null id：%s", caseId));
        return covertToCaseDetail(recordDetail);
    }


    @Override
    public void addWhite(Long doctorId, String caseId) throws BusinessException {
        //获取医生信息
        RecomUserInfoBO userInfoBO = remoter.getUserInfo(doctorId, null, false);
        if (userInfoBO == null || userInfoBO.getDoctor() == null) {
            throw new BusinessException(ExceptionCodes.DOCTOR_NOT_EXIST);
        }

        RecomDoctorBO doctorBO = userInfoBO.getDoctor();
        LOGGER.info("获取医生信息：doctorBo={}", doctorBO);

        DoctorInfoDTO doctorInfo = DoctorInfoDTO.builder()
                                                .doctorId(doctorBO.getId())
                                                .doctorName(doctorBO.getName())
                                                .departmentId(doctorBO.getDepartmentId())
                                                .departmentName(doctorBO.getDepartmentName())
                                                .hospitalId(doctorBO.getRecordHospitalId())
                                                .hospitalName(doctorBO.getHospitalName())
                                                .title(doctorBO.getTitle())
                                                .build();

        //添加病例白名单
        medicalRecordService.addWhite(caseId, doctorInfo);

    }

    @Override
    public PatientCaseDetailVO covertToCaseDetail(MedicalRecordDetailDTO s) {
        LOGGER.info("病例详情：dto={}", s.toString());
        PatientCaseDetailVO vo = new PatientCaseDetailVO();
        vo.setId(s.getId());
        vo.setDrRecordId(s.getId());

        //设置病例创建医生信息
        DoctorInfoDTO doctorInfo = s.getDoctors().stream().filter(
                dd -> dd.getRole() == DoctorInfoDTO.ROLE_CREATER).findFirst().get();
        BeanUtil.copyProperties(doctorInfo, vo);

        //设置患者个人信息
        BeanUtil.copyProperties(s.getPatientInfo(), vo);
        vo.setAge(s.getPatientInfo().getAgeStr());
        vo.setHospitalName(EHP_HOSPITAL_NAME);
        //病例详情和签名信息——兼容前端显示
        DoctorMedicalRecordVO recordVO = new DoctorMedicalRecordVO();
        BeanUtil.copyProperties(s.getRecord(), recordVO);
        MenstrualVO menstrual = new MenstrualVO();
        if (null != s.getRecord().getMenstrual()) {
            BeanUtil.copyProperties(s.getRecord().getMenstrual(), menstrual);
        }
        recordVO.setMenstrual(menstrual);

        //设置图片数据
        if (!CollectionUtils.isEmpty(s.getRecord().getImgList())) {
            recordVO.setImgList(s.getRecord().getImgList().stream().map(img -> ImgFileVO.builder()
                                                                                        .imgUrl(img.getUrl())
                                                                                        .uuid(img.getUuid())
                                                                                        .build()).collect(Collectors.toList()));
        }

        BeanUtil.copyProperties(s.getSignInfo(), recordVO);
        //现病史特殊处理，没有显示无
        recordVO.setPresentDisease(StringUtils.isBlank(recordVO.getPresentDisease()) ? "无" : recordVO.getPresentDisease());
        vo.setDoctorMedicalRecord(recordVO);

        //创建时间
        vo.setFinishTime(s.getCreatedAt().getTime());
        vo.setFinishTimeDate(s.getCreatedAt());

        //设置签名信息
        SignInfoVO signInfo = new SignInfoVO();
        BeanUtil.copyProperties(s.getSignInfo(), signInfo);
        RecomUserInfoBO userInfoBO = null;
        try {
            userInfoBO = remoter.getUserInfo(doctorInfo.getDoctorId(), null, false);
            signInfo.setSealImage(userInfoBO.getDoctor().getSealImage());
        } catch (BusinessException e) {
            LOGGER.error("获取医生签名图片失败：doctorId={}", doctorInfo.getDoctorId());
        }
        vo.setMedicalRecordSettingList(s.getRecord().getMedicalRecordSettingList());
        vo.setSignInfo(signInfo);
        return vo;
    }

    @Override
    public String caseSignPdfUrl(String recordId) throws BusinessException {
        MedicalRecord medicalRecord = medicalRecordRepository.get(recordId);
        SignInfo signInfo = medicalRecord.getSignInfo();
        if (null != signInfo && CollectionUtil.isNotEmpty(signInfo.getFiles())) {
            List<SignInfo.FileInfo> files = signInfo.getFiles();
            List<SignInfo.FileInfo> signfiles =
                    files.stream().filter(file -> file.getType().equals(SignInfo.FILE_TYPE_SIGN)).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(signfiles)) {
                // 如果有签名过的文件，则去签名文件
                return imgDomain + signfiles.get(0).getPath();
            } else {
                // 否则随机取一条
                return imgDomain + files.get(0).getPath();
            }
        }
        return "";
    }
}
